import { getUserPermissions } from "../../utils/access"

// components/poster/index.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    // 海报宽度
    width: {
      type: Number,
      value: 750,
    },
    // 海报高度
    height: {
      type: Number,
      value: 1050,
    },
  },
  /**
   * 组件的初始数据
   */
  data: {
  },
  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 初始化
     * @param {*} callback 回调函数
     */
    init(callback) {
      const query = this.createSelectorQuery()
      query.select('#poster')
        .fields({ node: true, size: true })
        .exec((res) => {
          const canvas = res[0].node
          const ctx = canvas.getContext('2d')

          const dpr = wx.getSystemInfoSync().pixelRatio
          canvas.width = res[0].width * dpr
          canvas.height = res[0].height * dpr
          if (!canvas.width || !canvas.height) {
            console.error('Canvas element with a width or height of 0.')
          }
          ctx.scale(dpr, dpr)

          this.canvas = canvas
          this.ctx = ctx

          callback?.(this)
        })
    },
    /**
     * 添加容器
     * @param {*} options 容器配置
     * @param {number} options.width 容器宽度
     * @param {number} options.height 容器高度
     * @param {number} options.top 容器距离海报上边距离
     * @param {number} options.left 容器距离海报左边距离
     * @param {string} options.background 容器背景色
     * @param {number} options.radius 容器圆角
     * @param {number} options.borderWidth 容器边框宽度
     * @param {number} options.borderColor 容器边框颜色
     * @param {number} options.rotate 容器旋转角度 0-360
     */
    view(options) {
      if (!this.ctx) {
        console.error('Canvas Context is undefined.')
        return
      }
      this.ctx.save()
      this.ctx.beginPath()
      // 圆角
      if (options?.radius) {
        this.radius(options)
      }
      // 旋转
      if (+options?.rotate) {
        this.ctx.rotate(+options?.rotate * Math.PI / 180)
      }
      // 矩形
      this.ctx.fillStyle = options?.background || '#fff'
      this.ctx.fillRect(
        this.rpxToPx(options?.left || 0),
        this.rpxToPx(options?.top || 0),
        this.rpxToPx(options?.width || 0),
        this.rpxToPx(options?.height || 0)
      )
      this.ctx.closePath()
      this.ctx.restore()
      // 边框
      this.border(options)
    },
    /**
     * 添加文字
     * @param {*} options 文字配置
     * @param {string} options.content 文字文本
     * @param {number} options.color 文字颜色
     * @param {number} options.fontSize 文字大小
     * @param {string} options.textAlign 文字对齐方式 left center right
     * @param {number} options.top 文字距离海报上边距离
     * @param {number} options.left 文字距离海报左边距离
     * @param {number} options.rotate 文字旋转角度 0-360
     * @param {number} options.fontWeight 文字加粗 400-800 bold
     * @param {number} options.fontFamily 文字字体 sans-serif
     */
    text(options) {
      if (!this.ctx) {
        console.error('Canvas Context is undefined.')
        return
      }
      this.ctx.save()
      // 旋转
      if (+options?.rotate) {
        this.ctx.rotate(+options?.rotate * Math.PI / 180)
      }
      const fontSize = this.rpxToPx(options?.fontSize || 10)
      const content = options?.content || ''
      this.ctx.fillStyle = options?.color || '#333'
      this.ctx.font = `${options?.fontWeight || 400} ${fontSize}px ${options?.fontFamily || 'sans-serif'}`
      this.ctx.textAlign = options?.textAlign || 'left'
      this.ctx.fillText(
        content,
        this.rpxToPx(options?.left || 0),
        this.rpxToPx(options?.top || 0),
      )
      const measureTextInfo = this.ctx.measureText(content)
      this.ctx.restore()
      // 返回文字信息
      return measureTextInfo
    },
    /**
     * 添加图片
     * @param {*} options 图片配置
     * @param {number} options.width 图片宽度
     * @param {number} options.height 图片高度
     * @param {number} options.top 图片距离海报上边距离
     * @param {number} options.left 图片距离海报左边距离
     * @param {number} options.radius 图片圆角
     * @param {number} options.borderWidth 图片边框宽度
     * @param {number} options.borderColor 图片边框颜色
     * @param {number} options.rotate 图片旋转角度 0-360
     */
    async image(options) {
      if (!this.canvas) {
        console.error('Canvas is undefined.')
        return
      }
      if (!this.ctx) {
        console.error('Canvas Context is undefined.')
        return
      }
      return new Promise((resolve) => {
        const image = this.canvas.createImage()
        image.src = options?.src
        image.onload = () => {
          this.ctx.save()
          this.ctx.beginPath()
          // 圆角
          if (options?.radius) {
            this.radius(options)
          }
          // 旋转
          if (+options?.rotate) {
            this.ctx.rotate(+options?.rotate * Math.PI / 180)
          }
          // 图片坐标
          const x = this.rpxToPx(options?.left || 0)
          const y = this.rpxToPx(options?.top || 0)
          // 图片真实宽高
          const w = image.width
          const h = image.height
          // 图片显示宽高
          const cw = this.rpxToPx(options?.width || 0)
          const ch = this.rpxToPx(options?.height || 0)
          // 图片的宽高比
          const dw = cw / w
          const dh = ch / h

          // 裁剪图片中间部分
          if (w > cw && h > ch || w < cw && h < ch) {
            if (dw > dh) {
              this.ctx.drawImage(image, 0, (h - ch / dw) / 2, w, ch / dw, x, y, cw, ch)
            } else {
              this.ctx.drawImage(image, (w - cw / dh) / 2, 0, cw / dh, h, x, y, cw, ch)
            }
          }
          // 拉伸图片
          else {
            if (w < cw) {
              this.ctx.drawImage(image, 0, (h - ch / dw) / 2, w, ch / dw, x, y, cw, ch)
            } else {
              this.ctx.drawImage(image, (w - cw / dh) / 2, 0, cw / dh, h, x, y, cw, ch)
            }
          }
          this.ctx.closePath()
          this.ctx.restore()
          // 边框
          this.border(options)
          resolve()
        }
      })
    },
    /**
     * 绘制圆角
     * @param {*} options 圆角配置
     * @param {number} options.radius 圆角半径
     * @param {number} options.width 圆角容器宽度
     * @param {number} options.height 圆角容器高度
     * @param {number} options.top 圆角容器距离海报上边距离
     * @param {number} options.left 圆角容器距离海报左边距离
     */
    radius(options) {
      if (!this.ctx) {
        console.error('Canvas Context is undefined.')
        return
      }
      const r = this.rpxToPx(options?.radius || 0)
      const x = this.rpxToPx(options?.left || 0)
      const y = this.rpxToPx(options?.top || 0)
      const w = this.rpxToPx(options?.width || 0)
      const h = this.rpxToPx(options?.height || 0)
      // 左上角
      this.ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
      // 右上角
      this.ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
      // 右下角
      this.ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
      // 左下角
      this.ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
      // 裁切
      this.ctx.clip()
    },
    /**
     * 绘制边框
     * @param {*} options 边框配置
     * @param {number} options.borderWidth 边框宽度
     * @param {string} options.borderColor 边框颜色
     */
    border(options) {
      if (!this.ctx) {
        console.error('Canvas Context is undefined.')
        return
      }
      const lineWidth = this.rpxToPx(options?.borderWidth || 0)
      if (lineWidth) {
        this.ctx.strokeStyle = options?.borderColor || '#F5F5F5'
        this.ctx.lineWidth = lineWidth
        this.ctx.stroke()
      }
    },
    /**
     * 单位转换
     * @param {number} pixel 像素rpx
     */
    rpxToPx(pixel) {
      if (pixel) {
        // px转换到rpx的比例
        const pxToRpxScale = 750 / wx.getSystemInfoSync().windowWidth
        return pixel / pxToRpxScale
      }
      return 0
    },
    /**
     * 单位转换
     * @param {number} pixel 像素px
     */
    pxToRpx(pixel) {
      if (pixel) {
        // px转换到rpx的比例
        const pxToRpxScale = 750 / wx.getSystemInfoSync().windowWidth
        return pixel * pxToRpxScale
      }
      return 0
    },
    /**
     * 转换图片
     * @param {*} callback 回调函数
     */
    toPicture(callback) {
      if (!this.canvas) {
        console.error('Canvas is undefined.')
        return
      }
      wx.canvasToTempFilePath({
        canvas: this.canvas,
        success: (res) => {
          callback?.(res)
          console.log('canvas转图片成功', res)
        },
        fail(err) {
          callback?.()
          console.log('canvas转图片失败', err)
          wx.showToast({
            title: 'canvas转图片失败',
            icon: 'error'
          })
        }
      }, this)
    },
    /**
     * 保存图片
     * @param {*} callback 回调函数
     */
    savePicture(callback) {
      this.toPicture((result) => {
        if (result) {
          // 调用系统方法，下载图片并保存
          getUserPermissions('writePhotosAlbum', (res) => {
            callback?.(res)
            if (res) {
              wx.showToast({
                title: '保存成功',
                icon: 'success'
              })
            } else {
              wx.showToast({
                title: '保存失败',
                icon: 'error'
              })
            }
          }, { filePath: result.tempFilePath })
        }
      })
    },
  },
})
